
;			NEC-APC.A86
;
;	For the NEC Advanced Personal Computer communications port.
;
;
;Change the clock speed to suit your system.
CLKRATE	EQU	5		;clock speed in MHz, 8 MHz maximum
;
;Do not change the next three equates.
SETUP	EQU	TRUE
DISCON	EQU	TRUE
CARDET	EQU	TRUE
SCRNCLR	EQU	TRUE
;
;8251A equates.
MODRCVB	EQU	02H		;bit to test for received data
MODRCVR	EQU	MODRCVB		;change to 0 if bit is 0 when
				;data received
MODSNDB	EQU	01H		;bit to test for ready to send
MODSNDR	EQU	MODSNDB		;change to 0 if bit is 0 when
				;ready to send
;
MODDATP	EQU	030H		;Serial Port 1 data
MODCTLP	EQU	032H		;Serial port 1 status
MODBAUD	EQU	02BH		;Counter/Timer 1 load
MODCLK	EQU	02FH		;Counter/Timer select 
;
ESCAPE	EQU	1BH
NULL	EQU	0
;
CLR1	EQU	ESCAPE		;ANSI clear from cursor to end of screen
CLR2	EQU	'['
CLR3	EQU	'0'
CLR4	EQU	'J'
;
SCLR1	EQU	ESCAPE		;ANSI clear entire screen
SCLR2	EQU	'['
SCLR3	EQU	'2'
SCLR4	EQU	'J'
SCLR5	EQU	1EH		;ADM3A home cursor
SCLR6	EQU	0
SCLR7	EQU	0
;
CLREOS:		CALL	ILPRT
;
		DB	CLR1,CLR2,CLR3,CLR4,0
		RET
;
CLRSCRN:	CALL	ILPRT
;
		DB	SCLR1,SCLR2,SCLR3,SCLR4,SCLR5,SCLR6,SCLR7,0
		RET
;
INMODCTLP:	IN	AL,MODCTLP		 ;in modem status port
		RET
		RB	OFFSET INMODCTLP-(offset $)+16  ;extra space

OUTMODDATP:	OUT	MODDATP,AL		 ;out modem data port
		RET
		RB	OFFSET OUTMODDATP-(offset $)+16 ;extra space

INMODDATP:	IN	AL,MODDATP		 ;in modem data port
		RET
		RB	OFFSET INMODDATP-(offset $)+16  ;extra space

ANIMODSNDB:	AND	AL,MODSNDB		 ;bit to test for send ready
		RET
		RB	OFFSET ANIMODSNDB-(offset $)+16 ;extra space

CPIMODSNDR:	CMP	AL,MODSNDR		 ;value of send bit when ready
		RET
		RB	OFFSET CPIMODSNDR-(offset $)+16 ;extra space

ANIMODRCVB:	AND	AL,MODRCVB		 ;bit to test for receive ready
		RET
		RB	OFFSET ANIMODRCVB-(offset $)+16 ;extra space

CPIMODRCVR:	CMP	AL,MODRCVR		 ;value of receive ready bit
		RET
;
;This is where the message goes giving the system for
;which MODEM9 has been customized.
;
SYSVER:
	CALL	ILPRT
	DB	'Set Up for: NEC Advanced Personal Computer',CR,LF
	DB	'            on standard serial port',CR,LF,LF,0
	RET
;
;The following are used in setting up the 8251A
;No need to change for another micro if INIT and SETUP are FALSE.
;
;control bytes
RSTINS	EQU	40H	;reset 8251A
RSTERR	EQU	37H	;reset parity and overrun flags
MODEINS	EQU	4EH	;16x, 8 bits, no parity, 1 stop
CMDINS	EQU	27H	;DTR, RTS, Tx enable, RX enable
CLK16	EQU	02H	;16X baud rate
CLKSET	EQU	076H	;Select baud rate counter/timer
STSPEED	EQU	1	;300bps
;End of 8251A specific equates for initialization.
;
;
;The following is used to initialize the 8251A on execution
;of MODEM9.
;
INITMOD:
	MOV	AL,CLKSET
	OUT	MODCLK,AL	;Select baud rate generator
	MOV	AL,STSPEED
INITSPD	EQU	Offset $ - 1
	MOV	MSPEED,AL
	MOV	BX,Offset BDTABL ;Set baud rate	
	MOV	DX,0
	ADD	AL,AL
	MOV	DL,AL
	ADD	BX,DX
	MOV	AX,[BX]
	OUT	MODBAUD,AL	;Set low byte of clock
	MOV	AL,AH
	OUT	MODBAUD,AL	;Set high byte of clock
	MOV	AL,NULL		;1st null
	OUT	MODCTLP,AL
	CALL	IDELAY
	MOV	AL,NULL		;2nd null
	OUT	MODCTLP,AL
	CALL	IDELAY
	MOV	AL,NULL		;3rd null
	OUT	MODCTLP,AL
	CALL	IDELAY
	MOV	AL,RSTINS	;Reset 8251A
	OUT	MODCTLP,AL
	CALL	IDELAY
	MOV	AL,MODEINS	;8251A mode byte
PARM1	EQU	OFFSET $ -1
	OUT	MODCTLP,AL
	CALL	IDELAY
	MOV	AL,CMDINS	;8251A command byte
PARM2	EQU	OFFSET $ -1
	OUT	MODCTLP,AL
	RET
;
IDELAY:
	NOP
	NOP
	NOP
	NOP
	RET
;
;The following routine changes the baud rate, stop bits and parity on
;the 8251A from the command level. Note the routine MUST modify the
;parameters used by the INITMOD routine.
;
;The following are parameters/masks used in setting word length
;stop bits and parity for the Z80 SIO.
MSKWD	EQU	0CH	;word length mask
SEVEN	EQU	08H	;receive seven bit word
EIGHT	EQU	0CH	;receive eight bit word
MSKST	EQU	0C0H	;stop bit mask
ONE	EQU	040H	;one stop bit
TWO	EQU	0C0H	;two stop bits
MSKPA	EQU	030H	;mask for parity bits
NONE	EQU	00H	;no parity
ODD	EQU	010H	;odd parity
EVEN	EQU	030H	;even parity
;
;
SETUPR:
	PUSH	BX
	CALL	CLRTST
	CALL	ILPRT
	DB	'                 UART/Modem Control',CR,LF,LF,LF
	DB	'Current settings -',CR,LF,0
	CALL	SETTIM2
	CALL	GIVEPRM
	CALL	ILPRT
	DB	CR,LF
	DB	'Enter choices below - <CR> for no change',CR,LF,0
AGAIN:
	MOV	DX,OFFSET BAUDBUF	;point to input buffer for ILCOMP
	CALL	ILPRT
	DB	'Baud Rate (110, 300, 600, 1200, 2400, 4800, 9600, 19200): ',0
	CALL	INBUFF
	MOV	DX,OFFSET BAUDBUF+2
	CALL	ILCOMP		;compare BAUDBUF+2 with characters below
	DB	'110',0
	MOV	AL,0
	JNC	OK		;go if got match
	CALL	ILCOMP
	DB	'300',0
	MOV	AL,1
	JNC	OK
	CALL	ILCOMP
	DB	'600',0
	MOV	AL,2
	JNC	OK
	CALL	ILCOMP
	DB	'1200',0
	MOV	AL,3
	JNC	OK
	CALL	ILCOMP
	DB	'2400',0
	MOV	AL,4
	JNC	OK
	CALL	ILCOMP
	DB	'4800',0
	MOV	AL,5
	JNC	OK
	CALL	ILCOMP
	DB	'9600',0
	MOV	AL,6
	JNC	OK
	CALL	ILCOMP
	DB	'19200',0
	MOV	AL,7
	JNC	OK
	CALL	ILCOMP
	DB	' ',0
	JNC	AGAIN2
	CALL	WRONG
	JMP	AGAIN		;try again
;
OK:
	MOV	CS: BYTE PTR .INITSPD,AL
	MOV	MSPEED,AL
;
AGAIN2:
	MOV	DX,OFFSET BAUDBUF	;point to input buffer for ILCOMP
	CALL	ILPRT
	DB	CR,LF
	DB	'Word Length (7, 8): ',0
	CALL	INBUFF
	MOV	DX,OFFSET BAUDBUF+2
	CALL	ILCOMP	;compare BAUDBUF+2 with characters below
	DB	'7',0
	MOV	AL,SEVEN
	JNC	OK2
	CALL	ILCOMP
	DB	'8',0
	MOV	AL,EIGHT
	JNC	OK2
	CALL	ILCOMP
	DB	' ',0
	JNC	AGAIN3
	CALL	WRONG
	JMP	AGAIN2
;
OK2:
	MOV	WDLEN,AL
;
AGAIN3:
	MOV	DX,OFFSET BAUDBUF ;point to input buffer for ILCOMP
	CALL	ILPRT
	DB	CR,LF
	DB	'Stop Bits (1, 2): ',0
	CALL	INBUFF
	MOV	DX,OFFSET BAUDBUF+2
	CALL	ILCOMP		;compare BAUDBUF+2 with characters below
	DB	'1',0
	MOV	AL,ONE
	JNC	OK3
	CALL	ILCOMP
	DB	'2',0
	MOV	AL,TWO
	JNC	OK3
	CALL	ILCOMP
	DB	' ',0
	JNC	AGAIN4
	CALL	WRONG
	JMP	AGAIN3
;
OK3:
	MOV	STPLN,AL
;
AGAIN4:
	MOV	DX,OFFSET BAUDBUF ;point to input buffer for ILCOMP
	CALL	ILPRT
	DB	CR,LF
	DB	'Parity (None, Even, Odd): ',0
	CALL	INBUFF
	MOV	DX,OFFSET BAUDBUF+2
	CALL	ILCOMP		;compare BAUDBUF+2 with characters below
	DB	'NONE',0
	MOV	AL,NONE
	JNC	OK4		;go if got match
	CALL	ILCOMP
	DB	'EVEN',0
	MOV	AL,EVEN
	JNC	OK4
	CALL	ILCOMP
	DB	'ODD',0
	MOV	AL,ODD
	JNC	OK4
	CALL	ILCOMP
	DB	' ',0
	JNC	GOSET
	CALL	WRONG
	JMP	AGAIN4		;try again
;
OK4:
	MOV	PARIT,AL
;
GOSET:
	MOV	AL,0
	OR	AL,WDLEN
	OR	AL,PARIT
	OR	AL,STPLN
	OR	AL,CLK16
	MOV	CS: BYTE PTR .PARM1,AL
	CALL	ILPRT
	DB	CR,LF
	DB	'New settings -',CR,LF,0
	CALL	SETTIM2
	CALL	GIVEPRM
	POP	BX
	JMP	INITMOD		;reset Z80 SIO
;
GIVEPRM:
	CALL	GETPRM
	CALL	ILPRT
	DB	'Word length is ',0
	MOV	AL,WDLEN
	CMP	AL,SEVEN
	JNZ	NOTSEV
	CALL	ILPRT
	DB	'seven',0
	JMP	GIVEST
NOTSEV:
	CALL	ILPRT
	DB	'eight',0
GIVEST:
	CALL	ILPRT
	DB	', number of stop bits is ',0
	MOV	AL,STPLN
	CMP	AL,ONE
	JNZ	NOTONE
	CALL	ILPRT
	DB	'one',0
	JMP	GIVEPA
NOTONE:
	CALL	ILPRT
	DB	'two',0
GIVEPA:
	CALL	ILPRT
	DB	', parity is ',0
	MOV	AL,PARIT
	CMP	AL,NONE
	JNZ	NOTNON
	CALL	ILPRT
	DB	'none',CR,LF,0
	RET

NOTNON:
	MOV	AL,PARIT
	CMP	AL,ODD
	JNZ	NOTODD
	CALL	ILPRT
	DB	'odd',CR,LF,0
	RET
NOTODD:
	CALL	ILPRT
	DB	'even',CR,LF,0
	RET
;
GETPRM:
	MOV	AL,CS: BYTE PTR .PARM1	;get present word length
	AND	AL,MSKWD	
	MOV	WDLEN,AL
	MOV	AL,CS: BYTE PTR .PARM1	;get stop bits and parity
	MOV	CH,AL
	AND	AL,MSKST
	MOV	STPLN,AL
	MOV	AL,CH
	AND	AL,MSKPA
	MOV	PARIT,AL
	RET
;
WRONG:
	CALL	ILPRT	;all matches failed - tell operator
	DB	'++ Incorrect entry ++',CR,LF,BELL,0
	RET
;
;Table of baud rate parameters
;
BDTABL	EQU	WORD PTR $
	DW      0574H		; 110 baud
	DW	0200H		; 300 baud
	DW	0100H		; 600 baud
	DW	0080H		; 1200 baud
	DW	0040H		; 2400 baud
	DW	0020H		; 4800 baud
	DW	0010H		; 9600 baud
	DW	0008H		; 19200 baud
;
WDLEN	DB	EIGHT
STPLN	DB	ONE
PARIT	DB	NONE
;
BAUDBUF:
	DB	10,0
	RB	10
;
;
;For MODEMs which disconnect from the telephone line when data terminal
;ready (DTR) drops, the following routine will disconnect.
;
HANGUP	EQU	0		;HANG UP THE TELEPHONE
;
DISCR:
	MOV	AL,25H
	OUT	MODCTLP,AL
	RET
;
;
;The following routine will give the carrier detect status
;
XTRAP	EQU	34H		;Extra status port
CTS	EQU	04H		;CLEAR TO SEND
RLSD	EQU	01H		;RECEIVED LINE SIGNAL (CARRIER) DETECT
;
DETCAR:
	MOV	AL,CARDETFLG
	OR	AL,AL
	JZ	DETCARRET	;RETURN IF FALSE
	CALL	ILPRT
	DB	'Carrier ',0
	IN	AL,XTRAP
	AND	AL,RLSD
	JNZ	DETCAR1
	CALL	ILPRT
	DB	'not ',0
DETCAR1:
	CALL	ILPRT
	DB	'present',CR,LF,0
DETCARRET:
	RET
;

